// 给你一个字符串表达式 s ，请你实现一个基本计算器来计算并返回它的值。
// 整数除法仅保留整数部分。

// 提示：

// s 由整数和算符 ('+', '-', '*', '/') 组成，中间由一些空格隔开
// s 表示一个 有效表达式
// 表达式中的所有整数都是非负整数
// 题目数据保证答案是一个 32-bit 整数

// 运算符类型
type Operators = "+" | '-' | '*' | '/';
// 运算符信息
interface OperatorInfo {
    priority: number;
    calculate: (a: number, b: number) => number;
}

const calculate = function (s: string): number {
    const numsStack: number[] = [];
    const operatorStack: Operators[] = [];
    const Operators = new Map<Operators, OperatorInfo>([
        ['+', { priority: 1, calculate: (a: number, b: number) => Math.floor(a + b) }],
        ['-', { priority: 1, calculate: (a: number, b: number) => Math.floor(a - b) }],
        ['*', { priority: 2, calculate: (a: number, b: number) => Math.floor(a * b) }],
        ['/', { priority: 2, calculate: (a: number, b: number) => Math.floor(a / b) }],
    ]);
    s = '0' + s.replace(/\s/g, ''); // 去掉所有空格，同时初始化一个0，防止第一个数字是负数（边界情况
    for (let i = 0; i < s.length; i++) {
        // 如果当前元素是数字
        if (!isNaN(parseInt(s[i], 10))) {
            let currIndex = i + 1;
            while (currIndex < s.length && Number.isNaN(parseInt(s[currIndex], 10)) === false) {
                currIndex++;
            }
            numsStack.push(parseInt(s.slice(i, currIndex), 10));
            i = currIndex - 1;
        } else {// 此时说明当前字符是运算符
            const currOperator = s[i] as Operators;
            // const nearestOperaor = operatorStack[operatorStack.length - 1];
            const currInfo = Operators.get(currOperator)!;
            // const nearestInfo = Operators.get(nearestOperaor)!;
            // 操作符栈不为空，尽可能地从左往右计算
            while (operatorStack.length > 0) {
                const nearestOperaor = operatorStack[operatorStack.length - 1];
                const nearestInfo = Operators.get(nearestOperaor) || null;
                // 判断运算的优先级顺序，当前操作符优先级大于栈内操作符优先级时不可运算
                if (nearestInfo && nearestInfo.priority >= currInfo.priority) {
                    const num2 = numsStack.pop()!;
                    const num1 = numsStack.pop()!;
                    operatorStack.pop();
                    // 入栈计算结果
                    numsStack.push(nearestInfo.calculate(num1, num2));
                } else {
                    break;
                }
            }
            operatorStack.push(currOperator);// 入栈当前运算符
        }
    }
    // 处理剩下运算符，此时剩下的元素顺序就是正确运算顺序
    while (operatorStack.length > 0) {
        const currOperator = operatorStack.pop()!;
        const num2 = numsStack.pop()!;
        const num1 = numsStack.pop()!;
        numsStack.push(Operators.get(currOperator)!.calculate(num1, num2));
    }
    return numsStack.pop()!;
};

console.log(calculate(" 3/2 "));